﻿using Dyao.Book.Contract;
using Foundation.Core;

namespace Dyao.Book.Application
{
    /// <summary>
    /// 任务中心执行管理器
    /// </summary>
    /// <typeparam name="TResult">任务执行过程信息</typeparam>
    /// <typeparam name="TExcutingInfo">执行结果</typeparam>
    public class TaskCenterManager<TResult, TExcutingInfo> : TaskCenterManager<TResult>, ITransientDependency
        where TExcutingInfo : class, new()
    {
        public TaskCenterManager(IServiceProvider serviceProvider)
            : base(serviceProvider)
        {
        }

        /// <summary>
        /// 开始任务，并创建<typeparamref name="TExcutingInfo"/>(任务执行过程信息)对象
        /// </summary>
        /// <returns></returns>
        public override Task StartAsync()
        {
            return UpdateCoreAsync(context =>
            {
                if (context.ExcuteBeginDatetime.HasValue)
                {
                    context.SetExecutedResult(null);
                }

                var info = new TExcutingInfo();
                var infoStr = Serialize(info);
                context.SetExecutingInfo(infoStr);

                UpdateStartInfo(context);
            },
            TaskCenterRecordStatusEnum.Pending,
            isLogComplete: false,
            logLevel:TaskCenterRecordLogTypeEnum.Business,
            logMessage: "任务开始执行");
        }

        /// <summary>
        /// 开始任务
        /// </summary>
        /// <param name="info">任务执行过程信息对象</param>
        /// <returns></returns>
        public Task StartAsync(TExcutingInfo info)
        {
            return UpdateCoreAsync(context =>
            {
                if (context.ExcuteBeginDatetime.HasValue)
                {
                    context.SetExecutedResult(null);
                }

                var infoString = Serialize(info);
                context.SetExecutingInfo(infoString);

                UpdateStartInfo(context);
            },
            TaskCenterRecordStatusEnum.Pending,
            isLogComplete: false,
            logLevel: TaskCenterRecordLogTypeEnum.Business,
            logMessage: "任务开始执行");

        }

        /// <summary>
        /// 更新任务执行过程信息
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public Task UpdateInfoAsync(Action<TExcutingInfo> action)
        {
            return UpdateCoreAsync(async context =>
            {
                var str = await context.GetExecutingInfoAsync();
                var info = Deserialize<TExcutingInfo>(str);
                action(info);

                var infoString = Serialize(info);
                context.SetExecutingInfo(infoString);
            },
            isLogComplete: false,
            logLevel: TaskCenterRecordLogTypeEnum.System,
            logMessage: "更新ExcutingInfo信息");
        }

        /// <summary>
        /// 更新任务执行过程信息
        /// </summary>
        /// <param name="action"></param>
        /// <param name="isAutoComplete"></param>
        /// <returns></returns>
        public Task UpdateInfoAsync(Action<TaskCenterRecordExcutingInfoModel<TExcutingInfo>> action, bool isAutoComplete = false)
        {
            return UpdateCoreAsync(async context =>
            {
                var str = await context.GetExecutingInfoAsync();
                var info = Deserialize<TExcutingInfo>(str);
                var model = LoadModel(context, new TaskCenterRecordExcutingInfoModel<TExcutingInfo>(info));
                action(model);

                var infoString = Serialize(info);
                context.SetExecutingInfo(infoString);
                StoreContext(context, model, isAutoComplete);
            },
            isLogComplete: false,
            logLevel: TaskCenterRecordLogTypeEnum.System,
            logFormatter: (context) => $"更新任务信息，任务进度{context.ExcutingProgress:f2}%");
        }


        /// <summary>
        /// 更新任务信息
        /// </summary>
        /// <param name="action">操作</param>
        /// <param name="isAutoComplete">是否自动推断是否已完成</param>
        /// <returns></returns>
        public Task UpdateAsync(Action<TaskCenterRecordInfoDto<TExcutingInfo, TResult>> action, bool isAutoComplete = false)
        {
            return UpdateCoreAsync(async context =>
            {
                var (infoStr, resultStr) = await context.GetExecutingInfoAndResultAsync();
                var info = Deserialize<TExcutingInfo>(infoStr);
                var result = Deserialize<TResult>(resultStr);

                var model = LoadModel(context, new TaskCenterRecordInfoDto<TExcutingInfo, TResult>(info));
                model.ExcuteResult = result;

                action(model);

                context.SetExecutingInfo(Serialize(info));
                context.SetExecutedResult(Serialize(result));

                StoreContext(context, model, isAutoComplete);
            },
            isLogComplete: isAutoComplete,
            logLevel: TaskCenterRecordLogTypeEnum.System,
            logFormatter: (context) => $"更新任务信息，任务进度{context.ExcutingProgress:f2}%");
        }
    }
}
